package main

import (
	"net"
	"os"

	"../pb"
	"../watcher"
	"github.com/op/go-logging"
	"github.com/valyala/fasthttp"
	"google.golang.org/grpc"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	check_conn   = kingpin.Flag("check", "check host is or not is connected.").String()
	ping_ips     = kingpin.Flag("ping", "ping ip address.").String()
	listen_addr  = kingpin.Flag("listen_addr", "listen address.").Short('l').String()
	auth_addr    = kingpin.Flag("auth_addr", "auth address.").Short('a').String()
	prome_addr   = kingpin.Flag("prome_addr", "prometheus address.").Short('p').String()
	log_file     = kingpin.Flag("log", "log file.").String()
	watcher_conf = kingpin.Flag("conf", "conf file.").Short('c').String()
	interval     = kingpin.Flag("interval", "interval.").Short('i').Int64()
	tags         = kingpin.Flag("tag", "tag key=value.").StringMap()
	confdir      = kingpin.Flag("confdir", "config directory.").String()
	log          = logging.MustGetLogger("watcher")
)

func checkErr(err error) {
	if err != nil {
		log.Error(err)
		os.Exit(2)
	}
}

func main() {
	kingpin.Parse()

	conf := &config{}
	CheckConfdir(*confdir, conf)

	if conf.log_file == "" {
		bk := logging.NewLogBackend(os.Stderr, "", 0)
		logging.SetBackend(bk)
	} else {
		file, err := os.OpenFile(conf.log_file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
		checkErr(err)
		defer file.Close()
		bk := logging.NewLogBackend(file, "", 0)
		logging.SetBackend(bk)
	}

	lis, err := net.Listen("tcp", conf.listen_addr)
	checkErr(err)
	defer lis.Close()

	pws, err := watcher.NewProcWatcherService(conf.watcher_conf, conf.interval)
	checkErr(err)
	if conf.auth_addr != "" {
		pws.SetAuth(conf.auth_addr)
	}
	go pws.Refresh()
	defer pws.Close()

	metricMetric := watcher.NewMetrucExportor(conf.interval, conf.ping_ips, conf.check_conn, []string{"UpTimeAndProcs", "Load", "Misc", "VirtualMemory", "SwapMemory", "CPU", "NetIOCounters", "TcpStatus", "DiskUsage", "DiskIOCounters", "NetCheck", "NetPing"})
	go metricMetric.Refresh()
	defer metricMetric.Close()

	if prome_addr != nil {
		log.Infof("start prometheus export on %s", conf.prome_addr)
		log.Infof("using tags: %v", conf.tags)
		go fasthttp.ListenAndServe(conf.prome_addr, func(ctx *fasthttp.RequestCtx) {
			switch string(ctx.Path()) {
			case "/host":
				b, err := metricMetric.Export(conf.tags)
				if err != nil {
					log.Errorf("export prometheus error: %v", err)
					ctx.Error(err.Error(), fasthttp.StatusInternalServerError)
				} else {
					ctx.Success("text/plain; version=0.0.4", []byte(b))
				}
			case "/export":
				b, err := pws.Export(conf.tags)
				if err != nil {
					log.Errorf("export prometheus error: %v", err)
					ctx.Error(err.Error(), fasthttp.StatusInternalServerError)
				} else {
					ctx.Success("text/plain; version=0.0.4", []byte(b))
				}
			default:
				ctx.Error("", fasthttp.StatusNotFound)
			}
		})
	}

	pwatcher := grpc.NewServer()
	pb.RegisterWatcherServiceServer(pwatcher, pws)
	pwatcher.Serve(lis)
}
